home *** CD-ROM | disk | FTP | other *** search
/ Windows Expert / Windows Expert.iso / others / ole_101.zip / PATRON.ZIP / FILE.C < prev    next >
C/C++ Source or Header  |  1992-04-13  |  13KB  |  493 lines

  1. /*
  2.  * FILE.C
  3.  *
  4.  * Functions for handling dirty files and processing File menu commands.
  5.  *
  6.  * Functions:
  7.  *  WindowTitleSet
  8.  *  FDirtySet, FCleanVerify
  9.  *  FFileNew, FFileOpen, FFileSave, FFileSaveAs, FFileExit, FFileClose
  10.  *
  11.  * This file contains the only functions that manipulate the fDirty flag.
  12.  *
  13.  * Copyright(c) Microsoft Corp. 1992 All Rights Reserved
  14.  *
  15.  */
  16.  
  17. #include <windows.h>
  18. #include <ole.h>
  19. #include "oclient.h"
  20. #include "blackbox.h"
  21. #include "patron.h"
  22.  
  23.  
  24.  
  25. /*
  26.  * WindowTitleSet
  27.  *
  28.  * Purpose:
  29.  *  Handles changing the window's caption bar depending on the file
  30.  *  that is loaded.
  31.  *
  32.  * Parameters:
  33.  *  pGlob           LPGLOBALS to the global variable block.
  34.  *
  35.  * Return Value:
  36.  *  none.
  37.  */
  38.  
  39. void FAR PASCAL WindowTitleSet(LPGLOBALS pGlob)
  40.     {
  41.     char        szTitle[CCHPATHMAX];
  42.     LPSTR       pszT;
  43.  
  44.     pszT=pGlob->szFile;
  45.  
  46.     if (0!=lstrcmp(pszT, rgpsz[IDS_UNTITLED]))
  47.         pszT=PszFileFromPath(pGlob->szFile);
  48.  
  49.     wsprintf(szTitle, "%s - %s", (LPSTR)rgpsz[IDS_CAPTION], pszT);
  50.     SetWindowText(pGlob->hWnd, szTitle);
  51.     return;
  52.     }
  53.  
  54.  
  55.  
  56.  
  57.  
  58. /*
  59.  * FDirtySet
  60.  *
  61.  * Purpose:
  62.  *  Sets or clears the global 'dirty' flag returning the previous state
  63.  *  of that same flag.
  64.  *
  65.  * Parameters:
  66.  *  fDirty          BOOL used to set the value of the pGLob->fDirty flag.
  67.  *
  68.  * Return Value:
  69.  *  BOOL            Previous value of the dirty flag.
  70.  */
  71.  
  72. BOOL FAR PASCAL FDirtySet(BOOL fDirty)
  73.     {
  74.     BOOL        fPrevious;
  75.  
  76.     fPrevious=pGlob->fDirty;
  77.     pGlob->fDirty=fDirty;
  78.  
  79.     return fPrevious;
  80.     }
  81.  
  82.  
  83.  
  84.  
  85.  
  86. /*
  87.  * FCleanVerify
  88.  *
  89.  * Purpose:
  90.  *  Checks the pGLob->fDirty flag, and if set, displays a message
  91.  *  box informing the user that the file is dirty and asking if
  92.  *  the file should be saved.  If the user chooses to save the
  93.  *  file, they are prompted with the File Save As dialog.
  94.  *
  95.  * Parameters:
  96.  *  pGlob           LPGLOBALS to global varaible block.
  97.  *
  98.  * Return Value:
  99.  *  BOOL            TRUE if
  100.  *                     1. The user saved the file
  101.  *                     2. The user said NO
  102.  *                     3. pGlob->fDirty is FALSE.
  103.  *
  104.  *                  FALSE if
  105.  *                     1. User pressed Cancel
  106.  *                     2. User pressed Yes but cancelled the Save As dialog.
  107.  */
  108.  
  109. BOOL FAR PASCAL FCleanVerify(LPGLOBALS pGlob, LPDOCUMENT pDoc)
  110.     {
  111.     BOOL        fRet;
  112.     DWORD       dwRet;
  113.     OLESTATUS   os;
  114.  
  115.     if (pGlob->fDirty)
  116.         {
  117.         dwRet=(DWORD)MessageBox(pGlob->hWnd, rgpsz[IDS_FILEDIRTY],
  118.                                 rgpsz[IDS_CAPTION], MB_YESNOCANCEL);
  119.  
  120.         switch (LOWORD(dwRet))
  121.             {
  122.             case IDCANCEL:
  123.                 fRet=FALSE;
  124.                 break;
  125.  
  126.             case IDNO:
  127.                 /*
  128.                  * Inform OLECLI that this document was not changed on disk
  129.                  * since the last save.
  130.                  */
  131.                 os=OleRevertClientDoc(pDoc->lh);
  132.                 fRet=(OLE_OK==os);
  133.                 break;
  134.  
  135.             case IDYES:
  136.                 fRet=FFileSave(pGlob, pDoc, FALSE);
  137.                 break;
  138.             }
  139.         }
  140.  
  141.     return fRet;
  142.     }
  143.  
  144.  
  145.  
  146.  
  147.  
  148.  
  149. /*
  150.  * FFileNew
  151.  *
  152.  * Purpose:
  153.  *  Confirms the new file with the user and cleans out the Polyline
  154.  *  image.
  155.  *
  156.  * Parameters:
  157.  *  pGlob           LPGLOBALS to the global variable block.
  158.  *  pDoc            LPDOCUMENT of the document holding objects.
  159.  *
  160.  * Return Value:
  161.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  162.  *
  163.  */
  164.  
  165. BOOL FAR PASCAL FFileNew(LPGLOBALS pGlob, LPDOCUMENT pDoc)
  166.     {
  167.     if (!FCleanVerify(pGlob, pDoc))
  168.         return FALSE;
  169.  
  170.     //Release all the object windows.
  171.     FFileClose(pGlob, pDoc);
  172.  
  173.     lstrcpy(pGlob->szFile, rgpsz[IDS_UNTITLED]);
  174.     WindowTitleSet(pGlob);
  175.  
  176.     //Act like we're starting the applciation again with no initial file.
  177.     return FFileOpen(pGlob, pDoc, TRUE);
  178.     }
  179.  
  180.  
  181.  
  182.  
  183.  
  184. /*
  185.  * FFileOpen
  186.  *
  187.  * Purpose:
  188.  *  Reads the contents of a file.  If fStartup is TRUE, we assume that
  189.  *  pGlob->szFile contains a startup filename or just NULLs, in which
  190.  *  case we use '(Untitled).'  If fStartup is FALSE, then we prompt the
  191.  *  user to save changes if ncessary and retrieve a new file to open.
  192.  *
  193.  * Parameters:
  194.  *  pGlob           LPGLOBALS to the global variable block.
  195.  *  pDoc            LPDOCUMENT of the document holding objects.
  196.  *  fStartup        BOOL indicates if the function is being called
  197.  *                  to load an initial file on startup (TRUE) or if
  198.  *                  it's in response to a user's menu choice (FALSE).
  199.  *
  200.  * Return Value:
  201.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  202.  *
  203.  */
  204.  
  205. BOOL FAR PASCAL FFileOpen(LPGLOBALS pGlob, LPDOCUMENT pDoc, BOOL fStartup)
  206.     {
  207.     OLESTATUS       os;
  208.     PATRON          ptn;
  209.     BOOL            fOK=TRUE;
  210.     BOOL            fUntitled=FALSE;
  211.  
  212.     if (!fStartup)
  213.         {
  214.         if (!FCleanVerify(pGlob, pDoc))
  215.             return FALSE;
  216.  
  217.         fOK=FFileDialog(pGlob->hWnd, pGlob->hInst, rgpsz[IDS_DEFEXT],
  218.                         rgpsz[IDS_FILEOPENFILTER], pGlob->szFile,
  219.                         rgpsz[IDS_FILEOPEN], TRUE);
  220.  
  221.         /*
  222.          * If the user pressed Cancel in the dialog, then we're still OK.
  223.          * Nothing has yet caused an error.
  224.          */
  225.         if (!fOK)
  226.             return TRUE;
  227.  
  228.         //Clean out the existing document.
  229.         FFileClose(pGlob, pDoc);
  230.         }
  231.     else
  232.         {
  233.         if (0==pGlob->szFile[0])
  234.             {
  235.             lstrcpy(pGlob->szFile, rgpsz[IDS_UNTITLED]);
  236.             fUntitled=TRUE;
  237.             }
  238.         }
  239.  
  240.     WindowTitleSet(pGlob);
  241.  
  242.     /*
  243.      * OLE: Register a new client document with the given filename. If
  244.      * we're starting, then this is the filename we had on the command
  245.      * line or it's '(Untitled).'
  246.      */
  247.     os=OleRegisterClientDoc(rgpsz[IDS_CLASSPATRON], pGlob->szFile, 0L, &pDoc->lh);
  248.  
  249.     if (OLE_OK!=os)
  250.         return FALSE;
  251.  
  252.     //If we have a filename, attempt to load it.
  253.     if (!fUntitled)
  254.         {
  255.         if (FPtnFileRead(pGlob->szFile, &ptn, pGlob->hWnd, pDoc))
  256.             {
  257.             //If opening succeeds, move the window and update links.
  258.             SetWindowPos(pGlob->hWnd, NULL, ptn.rc.left, ptn.rc.top,
  259.                          ptn.rc.right-ptn.rc.left, ptn.rc.bottom-ptn.rc.top,
  260.                          SWP_NOZORDER);
  261.  
  262.             pGlob->fOpenFile=TRUE;
  263.  
  264.             /*
  265.              * OLE:  Ask the user if they want to update automatic AND
  266.              * manual links and do so if they respond Yes.  FOLELinksUpdate
  267.              * only cares if FPtnFileRead counted any non-updated links.
  268.              */
  269.             FOLELinksUpdate(pGlob->hWnd, pGlob->hInst, pDoc);
  270.             fOK=TRUE;
  271.             }
  272.         else
  273.             {
  274.             //If opening fails, then rename the document to '(Untitled).'
  275.             lstrcpy(pGlob->szFile, rgpsz[IDS_UNTITLED]);
  276.             WindowTitleSet(pGlob);
  277.  
  278.             os=OleRenameClientDoc(pDoc->lh, pGlob->szFile);
  279.  
  280.             fOK=(OLE_OK==os);
  281.             }
  282.         }
  283.  
  284.     FDocumentFileSet(pDoc, pGlob->szFile);
  285.     FDirtySet(FALSE);
  286.     return fOK;
  287.     }
  288.  
  289.  
  290.  
  291.  
  292.  
  293.  
  294. /*
  295.  * FFileSave
  296.  *
  297.  * Purpose:
  298.  *  Writes the file to a known filename, requiring that the user has
  299.  *  previously used FileOpen or FileSaveAs in order to have a filename.
  300.  *
  301.  * Parameters:
  302.  *  pGlob           LPGLOBALS to the global variable block.
  303.  *  pDoc            LPDOCUMENT of the document holding objects.
  304.  *  fSaveAs         BOOL indicates if this is being called as a result
  305.  *                  of a FileSaveAs, in which case we change the call
  306.  *                  to OleSavedClientDoc to OleRenameClientDoc.
  307.  *
  308.  * Return Value:
  309.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  310.  *
  311.  */
  312.  
  313. BOOL FAR PASCAL FFileSave(LPGLOBALS pGlob, LPDOCUMENT pDoc, BOOL fSaveAs)
  314.     {
  315.     OLESTATUS       os;
  316.     PATRON          ptn;
  317.  
  318.     /*
  319.      * Note:  Calling FFileSaveAs will reenter this function as well,
  320.      * but always with fSaveAs==TRUE, so we'll never get stuck in a loop.
  321.      */
  322.     if (!pGlob->fOpenFile && !fSaveAs)
  323.         return FFileSaveAs(pGlob, pDoc);
  324.  
  325.     //Get the data.
  326.     ptn.wVerMajor=VERSIONMAJOR;
  327.     ptn.wVerMinor=VERSIONMINOR;
  328.     GetWindowRect(pGlob->hWnd, &ptn.rc);
  329.  
  330.     //Indicate how many objects we store here.  One object per BlackBox.
  331.     ptn.cObjects=pDoc->cObjects;
  332.  
  333.     //Go write the mess.
  334.     if (!FPtnFileWrite(pGlob->szFile, &ptn, pDoc))
  335.         return FALSE;
  336.  
  337.     //Note that FFileSaveAs calls WindowTitleSet for this new name.
  338.     if (fSaveAs)
  339.         {
  340.         os=OleRenameClientDoc(pDoc->lh, pGlob->szFile);
  341.         FDocumentFileSet(pDoc, pGlob->szFile);
  342.         }
  343.     else
  344.         os=OleSavedClientDoc(pDoc->lh);
  345.  
  346.     FDirtySet(FALSE);
  347.     pGlob->fOpenFile=TRUE;
  348.     return TRUE;
  349.     }
  350.  
  351.  
  352.  
  353.  
  354.  
  355.  
  356. /*
  357.  * FFileSaveAs
  358.  *
  359.  * Purpose:
  360.  *  Invokes the common dialog for Save As to get a filename then
  361.  *  writes the PATRON data to that file, creating if necessary.
  362.  *
  363.  * Parameters:
  364.  *  pGlob           LPGLOBALS to the global variable block.
  365.  *  pDoc            LPDOCUMENT of the document holding objects.
  366.  *
  367.  * Return Value:
  368.  *  BOOL            TRUE if the function succeeded, FALSE otherwise.
  369.  *
  370.  */
  371.  
  372. BOOL FAR PASCAL FFileSaveAs(LPGLOBALS pGlob, LPDOCUMENT pDoc)
  373.     {
  374.     BOOL            fOK;
  375.  
  376.     //Go retrieve a new filename.
  377.     fOK=FFileDialog(pGlob->hWnd, pGlob->hInst, rgpsz[IDS_DEFEXT],
  378.                     rgpsz[IDS_FILEOPENFILTER], pGlob->szFile,
  379.                     rgpsz[IDS_FILESAVEAS], FALSE);
  380.  
  381.  
  382.     if (fOK)
  383.         {
  384.         //We now have a filename, so take advantage of FFileSave.
  385.         fOK=FFileSave(pGlob, pDoc, TRUE);
  386.         pGlob->fOpenFile=fOK;
  387.  
  388.         if (fOK)
  389.             WindowTitleSet(pGlob);
  390.         }
  391.  
  392.     return fOK;
  393.     }
  394.  
  395.  
  396.  
  397.  
  398. /*
  399.  * FFileExit
  400.  *
  401.  * Purpose:
  402.  *  Handles the File/Exit menu command, verifying dirty files as necessary.
  403.  *
  404.  * Parameters:
  405.  *  pGlob           LPGLOBALS to the global variable block.
  406.  *
  407.  * Return Value:
  408.  *  BOOL            TRUE if the application can exit, FALSE otherwise.
  409.  */
  410.  
  411. BOOL FAR PASCAL FFileExit(LPGLOBALS pGlob, LPDOCUMENT pDoc)
  412.     {
  413.     if (!FCleanVerify(pGlob, pDoc))
  414.         return FALSE;
  415.  
  416.     FFileClose(pGlob, pDoc);
  417.     return TRUE;
  418.     }
  419.  
  420.  
  421.  
  422.  
  423. /*
  424.  * FFileClose
  425.  *
  426.  * Purpose:
  427.  *  Closes a document, regardless of whether is was saved or not.
  428.  *  This function is meant to be used from operations like File Open
  429.  *  after that operation has saved any necessary changes.
  430.  *
  431.  * Parameters:
  432.  *  pGlob           LPGLOBALS to the global variable block.
  433.  *  pDoc            LPDOCUMENT of the document holding objects.
  434.  *
  435.  * Return Value:
  436.  *  BOOL            TRUE if the application can exit, FALSE otherwise.
  437.  */
  438.  
  439. BOOL FAR PASCAL FFileClose(LPGLOBALS pGlob, LPDOCUMENT pDoc)
  440.     {
  441.     OLESTATUS       os;
  442.  
  443.     //Release all objects and wait for each to receive OLE_RELEASE.
  444.     pDoc->cWait=0;
  445.     FObjectsEnumerate(pDoc, FEnumClose, 0L);
  446.     FOLEReleaseWait(TRUE, pDoc, NULL);
  447.  
  448.     //Clear all the windows.
  449.     SendMessage(pGlob->hWnd, WM_COMMAND, IDM_EDITCLEARALL, 0L);
  450.  
  451.     /*
  452.      * Tell OLECLI that this document is going away.  OleRevokeClientDoc
  453.      * does not return OLE_WAIT_FOR_RELEASE.
  454.      */
  455.  
  456.     os=OleRevokeClientDoc(pDoc->lh);
  457.  
  458.     pGlob->fOpenFile=FALSE;
  459.     FDirtySet(FALSE);
  460.     return (OLE_OK==os);
  461.     }
  462.  
  463.  
  464.  
  465.  
  466. /*
  467.  * FEnumClose
  468.  *
  469.  * Purpose:
  470.  *  Enumeration callback function for use from FFileClose when it
  471.  *  calls FObjectsEnumerate.  For each object we call OleRelease,
  472.  *  and if it returns OLE_WAIT_FOR_RELEASE we increment pDoc->cWait.
  473.  *  After this enumeration is complete, FFileClose can call FOLEReleaseWait
  474.  *  to wait for all objects.
  475.  *
  476.  * Parameters:
  477.  *  pDoc            LPDOCUMENT identifying the owner of all objects.
  478.  *  pObj            LPOBJECT identifying the current object.
  479.  *  dw              DWORD for extra data, unused.
  480.  *
  481.  * Return Value:
  482.  *  BOOL            TRUE--we want to enumerate everything.
  483.  */
  484.  
  485. BOOL FAR PASCAL FEnumClose(LPDOCUMENT pDoc, LPOBJECT pObj, DWORD dw)
  486.     {
  487.     OLESTATUS       os;
  488.  
  489.     os=OleRelease(pObj->pObj);
  490.     OsError(os, pDoc, pObj, FALSE);
  491.     return TRUE;
  492.     }
  493.